package com.flida.bana.common.util;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;

import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.*;


public class MD5Util {

    static Logger logger = Logger.getLogger(com.flida.bana.common.util.MD5Util.class.getName());

    /**
     * 对待签名字符串使用MD5签名
     *
     * @param param
     * @return
     */
    public static String sign(String param) {

        if (null == param) {
            throw new RuntimeException("参数异常，获取待签名参数为空");
        }
        // 把验证码放在待签名字符串末形成新的待签名串
        String signStr = param;
        // 使用MD5签名函数对signStr签名
        signStr = md5(signStr);
        logger.debug("......签名字符串:" + signStr);
        return signStr;
    }

    /**
     * 对字符串进行MD5签名
     *
     * @param text 明文
     * @return 密文
     */
    public static String md5(String text) {
        return DigestUtils.md5Hex(getContentBytes(text, "utf-8"));
    }

    /**
     * 得到待签名字符串的字符流
     *
     * @param content
     * @param charset
     * @return
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    private static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"
                    + charset);
        }
    }

    public static void main(String args[]) throws Exception {
//		MD5Util md5Util = new MD5Util();
//
//		User user = new User();
//
//		System.out.println(MD5Util.md5("bkpay"));
//
//		user.setUsername("aaa");
//		user.setPassword("bbbb");
//		md5Util.signMD5(user, "123");
//		System.out.println(md5Util.signMD5(user,"8c4cc54c5f92694da03eed5409d57da1"));
//		System.out.println(md5Util.sign("applyNumber=A1352197186695&beginNumber=0&endNumber=3&name=测f124a4f10b4f58e03bfad28d2f50e626"));

    }

    public Map getFileValue(Object obj) {

        Map mapFileValue = null;
        if (null != obj) {
            try {

                mapFileValue = ClassUtil.getFileValue(obj);

            } catch (Exception e) {

                if (null == mapFileValue) {
                    mapFileValue = new HashMap();
                }
            }

        }
        return mapFileValue;
    }

    /**
     * 除去数组中的空值和签名参数
     *
     * @param sArray 签名参数组
     * @return 去掉空值与签名参数后的新签名参数组
     */
    private Map<String, String> paraFilter(Map<String, String> sArray) {

        Map<String, String> result = new HashMap<String, String>();
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            String value = sArray.get(key);
            if (value == null
                    // || key.equalsIgnoreCase("sign")
                    // || key.equalsIgnoreCase("sign_type")
                    || key.equalsIgnoreCase("connetKey")) {// 去掉签名参数
                continue;
            }
            result.put(key, value);
        }
        return result;
    }

    private String sortStringList(Map parament) {

        String resultStr = "";
        List<String> paramentList = new ArrayList<String>(parament.keySet());
        // 列表字母排序
        Collections.sort(paramentList);
        for (int i = 0; i < paramentList.size(); i++) {
            String key = paramentList.get(i);
            String value = (String) parament.get(key);

            if (i == paramentList.size() - 1) {// 拼接时，不包括最后一个&字符
                resultStr = resultStr + key + "=" + value;
            } else {
                resultStr = resultStr + key + "=" + value + "&";
            }
        }
        logger.debug("......待签名的字符串:" + resultStr);
        return resultStr;
    }

    public String signMD5(Object obj, String key) throws Exception {

        // 转换参数DTO 到map
        Map paraMap = ClassUtil.getFileValue(obj);
        // 去除参数中的null和connectkey
        paraMap = paraFilter(paraMap);
        // 获取待签名参数
        String para = sortStringList(paraMap);

        String applyNumber = (String) paraMap.get("applyNumber");
        String no_paraKey = para + key;
        logger.debug("待签名字符传为：" + no_paraKey);
        String yes_paraKey = sign(no_paraKey);
        logger.debug("签名后的字符传为：" + yes_paraKey);
        return yes_paraKey;
    }
}
